﻿Imports System.ComponentModel
Imports System.Threading
Imports System.Collections.ObjectModel
Imports System.Text
Imports iConverter.Models
Imports iConverter.Core
Imports iConverter.Extensions

Namespace ViewModels

    ''' <summary>
    ''' 主程序窗口的 ViewModel
    ''' </summary>
    ''' <remarks>用于MainWindow的 ViewModel ，包含 逻辑规则</remarks>
    Public Class iConverterViewModel
        Implements INotifyPropertyChanged

#Region "INotifyPropertyChanged 的实现 "

        ''' <summary>
        ''' 用来引发 PropertyChanged 事件，当属性被更改之后
        ''' </summary>
        ''' <param name="propName">属性名字</param>
        Private Sub Notify(ByVal propName As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
        End Sub

        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

#End Region

        ''' <summary>
        '''应用此ViewModel的窗体
        ''' </summary>
        ''' <remarks></remarks>
        Dim _win As MainWindow

        Public Sub New(ByVal win As MainWindow)

            'Dim settings = SettingManager.Settings 
            PluginsManager.Initialize()


            Me._SourceEncodingList = New ObservableCollection(Of Encoding)(EncodingManager.SourceEncodingList)
            Me._DestinationEncodingList = New ObservableCollection(Of Encoding)(EncodingManager.DestinationEncodingList)
            Me.IsAutoUsePostProcessings = SettingManager.Settings.isAutoUsePostProcessings


            Me._win = win
            win.DataContext = Me



            RegisterCommandBindings()

            RegisterWindowsEvent()

            AddHandler EncodingManager.EncodingListChanged, AddressOf UpdateEncodingList
            AddHandler PluginsManager.ProvidersChanged, AddressOf UpdatePlugins


        End Sub



        Protected Overrides Sub Finalize()
            RemoveHandler EncodingManager.EncodingListChanged, AddressOf UpdateEncodingList
            RemoveHandler PluginsManager.ProvidersChanged, AddressOf UpdatePlugins

            MyBase.Finalize()
        End Sub


#Region "编码列表 以及 文档相关信息"




        ''' <summary>
        ''' 文档集合
        ''' </summary>
        ''' <remarks></remarks>
        Dim _documentCollection As New ObservableCollection(Of ConvertDocument)

        ''' <summary>
        ''' 已选定文档索引
        ''' </summary>
        ''' <remarks></remarks>
        Dim _selectDocumentIndex As Integer = -1


        ''' <summary>
        ''' 目标编码列表
        ''' </summary>
        Private _DestinationEncodingList As ObservableCollection(Of Encoding)

        ''' <summary>
        ''' 源编码列表
        ''' </summary>
        Private _SourceEncodingList As ObservableCollection(Of Encoding)



        ''' <summary>
        ''' 目标编码列表
        ''' </summary>
        Public ReadOnly Property DestinationEncodingList() As ObservableCollection(Of Encoding)
            Get
                Return _DestinationEncodingList
            End Get
        End Property

        ''' <summary>
        ''' 源编码列表
        ''' </summary>
        Public ReadOnly Property SourceEncodingList() As ObservableCollection(Of Encoding)
            Get
                Return _SourceEncodingList
            End Get
        End Property

        ''' <summary>
        ''' 更新编码列表
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub UpdateEncodingList(sender As Object, e As EventArgs)
            Me._SourceEncodingList.Clear()
            EncodingManager.SourceEncodingList.ForEach(Sub(x)
                                                           Me._SourceEncodingList.Add(x)
                                                       End Sub)

            Me._DestinationEncodingList.Clear()
            EncodingManager.DestinationEncodingList.ForEach(Sub(x)
                                                                Me._DestinationEncodingList.Add(x)
                                                            End Sub)

            Me.Notify("SourceEncodingList")
            Me.Notify("DestinationEncodingList")

        End Sub


        ''' <summary>
        ''' 文档集合
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property DocumentCollection() As ObservableCollection(Of ConvertDocument)
            Get
                Return _documentCollection
            End Get
        End Property

        ''' <summary>
        ''' 指示打开的2个以上文档
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property isHaveMoreDocuments As Boolean
            Get
                Return Me.DocumentCollection.Count > 1
            End Get
        End Property

        ''' <summary>
        ''' 已选定文档索引
        ''' </summary>
        ''' <remarks></remarks>
        Public Property SelectDocumentIndex() As Integer
            Get
                Return _selectDocumentIndex
            End Get
            Set(ByVal value As Integer)
                _selectDocumentIndex = value
                Me.Notify("SelectDocumentIndex")
                Me.Notify("IsSelectDocument")
                Me.Notify("SelectDocument")
                Me.Notify("SelectDocumentSourceEncoding")
                Me.Notify("SelectDocumentDestinationEncoding")
                Me.Notify("isHaveMoreDocuments")
            End Set
        End Property

        ''' <summary>
        ''' 获取一个值，指示当前是否已选定文档
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property IsSelectDocument() As Boolean
            Get
                Return Me.SelectDocumentIndex >= 0 AndAlso Me.SelectDocumentIndex < Me.DocumentCollection.Count
            End Get
        End Property

        ''' <summary>
        ''' 获取当前是否已选定文档
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property SelectDocument() As ConvertDocument
            Get
                If Me.IsSelectDocument Then
                    Return Me.DocumentCollection(Me.SelectDocumentIndex)
                End If
                Return Nothing
            End Get
        End Property



        ''' <summary>
        ''' 获取当前选定文档的源编码
        ''' </summary>
        ''' <value>文档的Encoding对象</value>
        ''' <returns>如果当前选定了文档，则返回对应的源编码。否则返回Nothing</returns>
        ''' <remarks></remarks>
        Public Property SelectDocumentSourceEncoding As Encoding
            Get
                If IsSelectDocument Then
                    Return Me.SelectDocument.SourceEncoding
                End If
                Return Nothing
            End Get
            Set(ByVal value As Encoding)
                If IsSelectDocument Then
                    Me.SelectDocument.SourceEncoding = value
                End If
            End Set
        End Property

        ''' <summary>
        ''' 获取当前选定文档的目标编码
        ''' </summary>
        ''' <value>文档的Encoding对象</value>
        ''' <returns>如果当前选定了文档，则返回对应的目标编码。否则返回Nothing</returns>
        ''' <remarks></remarks>
        Public Property SelectDocumentDestinationEncoding As Encoding
            Get
                If IsSelectDocument Then
                    Return Me.SelectDocument.DestinationEncoding
                End If
                Return Nothing
            End Get
            Set(ByVal value As Encoding)
                If IsSelectDocument Then
                    Me.SelectDocument.SourceEncoding = value
                End If
            End Set
        End Property

#End Region


#Region "帮助 地址"





        ''' <summary>
        ''' iConverter 帮助
        ''' </summary>
        Public ReadOnly Property LinkHelp() As String
            Get
                Return "http://iconverter.codeplex.com/wikipage?title=Help"
            End Get
        End Property


        ''' <summary>
        ''' 开始使用
        ''' </summary>
        Public ReadOnly Property LinkStartUse() As String
            Get
                Return "http://iconverter.codeplex.com/wikipage?title=StartUse"
            End Get
        End Property

        ''' <summary>
        ''' 检查更新
        ''' </summary>
        Public ReadOnly Property LinkCheckUpdate() As String
            Get
                Return "http://iconverter.codeplex.com/releases"
            End Get
        End Property


        ''' <summary>
        ''' 访问iConverter项目网站
        ''' </summary>
        Public ReadOnly Property LinkWebSite() As String
            Get
                Return "http://iconverter.codeplex.com/"
            End Get
        End Property


        ''' <summary>
        ''' 寻求帮助
        ''' </summary>
        Public ReadOnly Property LinkPendingRequest() As String
            Get
                Return "http://iconverter.codeplex.com/discussions"
            End Get
        End Property


        ''' <summary>
        ''' 问题反馈
        ''' </summary>
        Public ReadOnly Property LinkFeedback() As String
            Get
                Return "http://iconverter.codeplex.com/workitem/list/basic"
            End Get
        End Property


        ''' <summary>
        ''' 与我联系
        ''' </summary>
        Public ReadOnly Property LinkContactus() As String
            Get
                Return "mailto:Guanyc.Dev+iConverter@Gmail.com?subject=iConverter"
            End Get
        End Property



#End Region


#Region "插件使用 以及相关"

        ''' <summary>
        ''' 获取或设置一个值用来指示是否自动使用后期处理插件
        ''' </summary>
        Private _IsAutoUsePostProcessings As Boolean

        ''' <summary>
        ''' 获取或设置一个值用来指示是否自动使用后期处理插件
        ''' </summary>
        ''' <value> </value>
        ''' <returns> </returns>
        ''' <remarks> </remarks>
        Public Property IsAutoUsePostProcessings As Boolean
            Get
                Return _IsAutoUsePostProcessings
            End Get
            Set(value As Boolean)
                _IsAutoUsePostProcessings = value
                Notify("IsAutoUsePostProcessings")
            End Set
        End Property




        ''' <summary>
        ''' 后期处理菜单项
        ''' </summary>
        ''' <remarks></remarks>
        Private _PostProcessingMenuItems As ObservableCollection(Of Fluent.MenuItem)


        ''' <summary>
        ''' 后期处理菜单项
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PostProcessingMenuItems() As ObservableCollection(Of Fluent.MenuItem)
            Get
                If Me._PostProcessingMenuItems Is Nothing Then
                    CreatePostProcessingMenuItems()
                End If
                Return _PostProcessingMenuItems
            End Get
        End Property

        ''' <summary>
        ''' 创建后期处理菜单项
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub CreatePostProcessingMenuItems()
            Me._PostProcessingMenuItems = New ObservableCollection(Of Fluent.MenuItem)

            'sltbtnAutoUsePostProcessings

            '<Fluent:MenuItem Header="{Binding Name}"  
            'IsEnabled="{Binding IsChecked, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Fluent:SplitButton}}}"
            '  ItemsSource="{Binding Processings }" 
            '     Icon="{Binding SmallIcon }" >

            '   <Fluent:MenuItem Header="{Binding Name}" 
            'Icon="{Binding SmallIcon }" IsCheckable="True"  IsChecked ="{Binding isSelected,Mode=TwoWay}" GroupName="{Binding GroupName}"/>


            Dim list = PluginsManager.PostProcessings

            Dim isEnableBinding As New Binding() With {.Source = Me, .Path = New PropertyPath("IsAutoUsePostProcessings")}


            For Each pp In list
                Dim menu1 As New Fluent.MenuItem With {.Header = pp.Name,
                                                       .Icon = pp.SmallIcon,
                                                       .DataContext = pp}

                menu1.SetBinding(Fluent.MenuItem.IsEnabledProperty, isEnableBinding)

                For Each p In pp.Processings
                    Dim menu2 As New Fluent.MenuItem With {.Header = p.Name,
                                                           .Icon = p.SmallIcon,
                                                           .IsCheckable = True,
                                                           .GroupName = p.GroupName,
                                                           .DataContext = p}

                    Dim isCheckBinding As New Binding() With {.Source = p, .Path = New PropertyPath("isSelected"), .Mode = BindingMode.TwoWay}

                    menu2.SetBinding(Fluent.MenuItem.IsCheckedProperty, isCheckBinding)

                    menu1.Items.Add(menu2)
                Next

                Me._PostProcessingMenuItems.Add(menu1)
            Next


        End Sub





        ''' <summary>
        ''' 插件提供器集合 
        ''' </summary>
        ''' <remarks></remarks>
        Private _PluginProcessers As ObservableCollection(Of Processer)


        ''' <summary>
        ''' 插件提供器集合 
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PluginProcessers() As ObservableCollection(Of Processer)
            Get
                If Me._PluginProcessers Is Nothing Then
                    CreatePluginPostProcessingsList()
                End If
                Return _PluginProcessers
            End Get
        End Property

        ''' <summary>
        ''' 创建后期处理插件列表
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub CreatePluginPostProcessingsList()
            Dim list = PluginsManager.Processers


            Me._PluginProcessers = New ObservableCollection(Of Processer)(list)

        End Sub


        ''' <summary>
        ''' 更新后期处理插件的处理器列表
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub UpdatePlugins(sender As Object, e As EventArgs)

            Dim tlist = Me._PostProcessingMenuItems.Concat(Me._PluginSendMenuItems)



            For Each item In tlist

                For Each item2 In item.Items
                    BindingOperations.ClearAllBindings(item2)
                Next

                BindingOperations.ClearAllBindings(item)
            Next

            Me._PostProcessingMenuItems.Clear()
            Me._PluginSendMenuItems.Clear()


            Me._PostProcessingMenuItems = Nothing
            Me._PluginSendMenuItems = Nothing


            Me.Notify("PostProcessingMenuItems")
            Me.Notify("PluginProcessers")
            Me.Notify("PluginSends")
            Me.Notify("PluginSendMenuItems")
        End Sub

#Region "发送到相关"


        ''' <summary>
        ''' 获取或设置一个值用来指示是否自动使用发送到插件
        ''' </summary>
        Private _IsAutoUseSend As Boolean

        ''' <summary>
        ''' 获取或设置一个值用来指示是否自动使用发送到插件
        ''' </summary>
        ''' <value> </value>
        ''' <returns> </returns>
        ''' <remarks> </remarks>
        Public Property IsAutoUseSend As Boolean
            Get
                Return _IsAutoUseSend
            End Get
            Set(value As Boolean)
                _IsAutoUseSend = value
                Notify("IsAutoUseSend")
            End Set
        End Property




        ''' <summary>
        ''' 发送到菜单项
        ''' </summary>
        ''' <remarks></remarks>
        Private _PluginSendMenuItems As ObservableCollection(Of Fluent.MenuItem)


        ''' <summary>
        ''' 发送到菜单项
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PluginSendMenuItems() As ObservableCollection(Of Fluent.MenuItem)
            Get
                If Me._PluginSendMenuItems Is Nothing Then
                    CreatePluginSendMenuItems()
                End If
                Return _PluginSendMenuItems
            End Get
        End Property

        ''' <summary>
        ''' 创建发送到单项
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub CreatePluginSendMenuItems()
            Me._PluginSendMenuItems = New ObservableCollection(Of Fluent.MenuItem)



            Dim list = PluginsManager.Sends

            Dim isEnableBinding As New Binding() With {.Source = Me, .Path = New PropertyPath("IsAutoUseSend")}


            For Each s In list
                Dim menu As New Fluent.MenuItem With {.Header = s.Name,
                                                       .Icon = s.SmallIcon,
                                                       .IsCheckable = True,
                                                       .GroupName = "PluginsSend",
                                                       .DataContext = s}

                menu.SetBinding(Fluent.MenuItem.IsEnabledProperty, isEnableBinding)

                

                Me._PluginSendMenuItems.Add(menu)
            Next


        End Sub





        ''' <summary>
        ''' 插件发送到插件集合 
        ''' </summary>
        ''' <remarks></remarks>
        Private _PluginSends As ObservableCollection(Of Send)


        ''' <summary>
        ''' 插件提供器集合 
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PluginSends() As ObservableCollection(Of Send)
            Get
                If Me._PluginSends Is Nothing Then
                    CreatePluginSendsList()
                End If
                Return _PluginSends
            End Get
        End Property

        ''' <summary>
        ''' 创建发送到插件列表
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub CreatePluginSendsList()
            Dim list = PluginsManager.Sends


            Me._PluginSends = New ObservableCollection(Of Send)(list)

        End Sub


#End Region
#End Region

    End Class

End Namespace
